﻿using In66.Net.Core.Core.Attributes;
using In66.Net.EventBus.RabbitMq;
using System.Linq.Dynamic.Core;

namespace In66.Net.Share.Registrar.WebRegistrar
{
    public static partial class ServiceRegistrar
    {
        /// <summary>
        /// 添加Controller
        /// </summary>
        /// <param name="Services"></param>
        /// <param name="Configuration"></param>
        /// <param name="ServiceInfo"></param>
        /// <returns></returns>
        public static IServiceCollection AddControllers(this IServiceCollection Services, IConfiguration Configuration, IServiceInfo ServiceInfo)
        {
            #region Json配置
            Services
                   .AddControllers(options =>
                   {
                       options.Filters.Add(typeof(CustomExceptionFilterAttribute));
                   })
                   .AddNewtonsoftJson(options =>
                   {
                       options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                       options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                       options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                       options.SerializerSettings.ContractResolver = NewtonTextJson.GetNullToEmptyStringResolver();
                   });

            //.AddJsonOptions(options =>
            //{
            //    options.JsonSerializerOptions.Converters.Add(new In66.Net.Core.System.Extensions.DataTimes.DateTimeConverter());
            //    options.JsonSerializerOptions.Converters.Add(new DateTimeNullableConverter());
            //    options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
            //    options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
            //    options.JsonSerializerOptions.Encoder = GetDefaultEncoder();
            //    options.JsonSerializerOptions.DictionaryKeyPolicy = GetNamePolicy(NameCase.Snake);
            //    options.JsonSerializerOptions.PropertyNamingPolicy = GetNamePolicy(NameCase.Snake);
            //}); 
            #endregion

            #region ApiBehaviorOptions
            Services
                    .Configure<ApiBehaviorOptions>(options =>
                    {
                        //调整参数验证返回信息格式
                        //关闭自动验证
                        //options.SuppressModelStateInvalidFilter = true;
                        //格式化验证信息
                        options.InvalidModelStateResponseFactory = (context) =>
                        {
                            var problemDetails = new Models.ResultModels.ProblemDetails
                            {
                                Detail = context.ModelState.GetValidationSummary("<br>"),
                                Title = "参数错误",
                                Status = (int)HttpStatusCode.BadRequest,
                                Type = "https://httpstatuses.com/400",
                                Instance = context.HttpContext.Request.Path
                            };

                            return new ObjectResult(problemDetails)
                            {
                                StatusCode = problemDetails.Status
                            };
                        };
                    });
            //add skyamp
            //_services.AddSkyApmExtensions().AddCaching(); 
            #endregion

            return Services;
        }

        /// <summary>
        /// 添加自动注入
        /// </summary>
        /// <param name="services"></param>
        public static IServiceCollection AddInjection(this IServiceCollection services)
        {
            var baseTypes = new[] { typeof(IScopedDependency), typeof(ITransientDependency), typeof(ISingletonDependency) };
            var types = IntegrationEventExtension.FindTypes(type =>
                (type is { IsClass: true, IsAbstract: false } && baseTypes.Any(b => b.IsAssignableFrom(type))) ||
                type.GetCustomAttribute<DependencyInjectionAttribute>() is not null);
            foreach (var implementedInterType in types)
            {
                var attr = implementedInterType.GetCustomAttribute<DependencyInjectionAttribute>();
                var typeInfo = implementedInterType.GetTypeInfo();
                var serviceTypes = typeInfo.ImplementedInterfaces
                                           .Where(x => x.HasMatchingGenericArity(typeInfo) && !x.HasAttribute<IgnoreDependencyAttribute>() && x != typeof(IDisposable))
                                           .Select(t => t.GetRegistrationType(typeInfo)).ToList();
                var lifetime = GetServiceLifetime(implementedInterType);
                if (lifetime is null)
                {
                    break;
                }

                if (serviceTypes.Count == 0)
                {
                    services.Add(new(implementedInterType, implementedInterType, lifetime.Value));
                    continue;
                }
                if (attr?.AddSelf is true)
                {
                    services.Add(new(implementedInterType, implementedInterType, lifetime.Value));
                }

                foreach (var serviceType in serviceTypes.Where(o => !o.HasAttribute<IgnoreDependencyAttribute>()))
                {
                    services.Add(new(serviceType, implementedInterType, lifetime.Value));
                }
            }

            return services;
        }

        /// <summary>
        /// 获取服务生命周期
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static ServiceLifetime? GetServiceLifetime(Type type)
        {
            var attr = type.GetCustomAttribute<DependencyInjectionAttribute>();
            return attr?.Lifetime ??
                   (typeof(IScopedDependency).IsAssignableFrom(type)
                        ? ServiceLifetime.Scoped
                        : typeof(ITransientDependency).IsAssignableFrom(type)
                            ? ServiceLifetime.Transient
                            : typeof(ISingletonDependency).IsAssignableFrom(type)
                                ? ServiceLifetime.Singleton
                                : null);
        }

        /// <summary>
        /// 判断特性相应是否存在
        /// </summary>
        /// <typeparam name="T">动态类型要判断的特性</typeparam>
        /// <param name="memberInfo"></param>
        /// <param name="inherit"></param>
        /// <returns>如果存在还在返回true，否则返回false</returns>
        public static bool HasAttribute<T>(this MemberInfo memberInfo, bool inherit = true) where T : Attribute => memberInfo.IsDefined(typeof(T), inherit);

        /// <summary>
        /// 获取注册类型
        /// </summary>
        /// <param name="interfaceType">接口类型.</param>
        /// <param name="typeInfo">对象类型</param>
        /// <returns></returns>
        public static Type GetRegistrationType(this Type interfaceType, TypeInfo typeInfo)
        {
            if (!typeInfo.IsGenericTypeDefinition)
            {
                return interfaceType;
            }

            var interfaceTypeInfo = interfaceType.GetTypeInfo();
            return interfaceTypeInfo.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType;
        }
    }
}
